// Loesung_von_Aufgabe_3.7_5_zwei_Berge

// Potenzialgebirge mit zwei Bergen und einem Trichter

float skalierung = 10; // Gibt die Größe einer Gitterzelle an
float rotationX = PI/4; // Rotation um die x-Achse (Startwert entspricht 45°)
float rotationZ = 0; // Rotation um die z-Achse
float positionZ = 0; // Verschiebung entlang der z-Achse
float[][] potenzialGebirge = new float[50][50]; // zweidimensionales Array zur Speicherung der Potenzialwerte

void setup()
{
  size(750, 750, P3D);

  // Das zweidimensionale Array wird mit Potenzialwerten gefüllt 
  for (int y = 0; y < 50; y++)
  {
    for (int x = 0; x < 50; x++)
    {
      potenzialGebirge[x][y] = 30/sqrt(pow(x - 10, 2) + pow(y - 10, 2) + 0.01) + 30/sqrt(pow(x - 10, 2) + pow(y - 40, 2) + 0.01) - 50/sqrt(pow(x - 40, 2) + pow(y - 25, 2) + 0.01);
    }
  }
}

/* Die folgende Funktion wird aufgerufen, wenn die Maustaste gedrückt ist
 und die Maus bewegt wird */
void mouseDragged() 
{
  /* Die Differenz der Mauskoordinaten (aktuelle Position und vorherige
   Position) wird verkleinert und zur Rotation entlang der x- bzw. z-Achse 
   addiert */
  rotationX += (mouseY - pmouseY) * -0.01;
  rotationZ += (mouseX - pmouseX) * -0.01;
}

// Die folgende Funktion ändert die Werte durch das Drehen des Mausrades
void mouseWheel(MouseEvent event)
{
  // Die Bewegung des Mausrads wird zur Verschiebung entlang der z-Achse addiert
  positionZ += event.getCount() * 100;
}

void draw()
{
  colorMode(RGB, 255, 255, 255); // Farbraum RGB für den Hintergrund
  background(255, 255, 255);
  stroke(0, 0, 0);
  strokeWeight(1);

  translate(width / 2, height / 2, 0); // Die Null dient hier als Hinweis, dass die z-Koordinate nicht verändert wird
  rotateX(rotationX);
  rotateZ(rotationZ);
  translate(0, 0, positionZ); // Das Koordinatensystem kann mit dem Mausrad in z-Richtung verschoben werden

  colorMode(HSB, 360, 100, 100); // Farbraum für das Potenzialgebirge

  // Zeichnet das Potenzialgebirge als eine mit Dreiecken dargestellte Oberfläche
  for (int y = 0; y < 50 - 1; y++)
  {
    beginShape(TRIANGLE_STRIP); // Siehe Abbildung in der Referenz zur Funktion beginShape()
    for (int x = 0; x < 50; x++)
    {    
      // Die Farben werden entsprechend der Potenzialgröße angepasst (HSB)
      fill(potenzialGebirge[x][y] * 50 + 180, 100, 100);
      vertex((x - 25) * skalierung, (y - 25) * skalierung, potenzialGebirge[x][y] * skalierung); 
      vertex((x - 25) * skalierung, (y - 25 + 1) * skalierung, potenzialGebirge[x][y + 1] * skalierung);
    }
    endShape();
  }
}